all repos — caroster @ 5b13f85e1cb3d6c7e11813397bd10bd6bc6b2b69

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid].tsx (view raw)

  1import {useState, useReducer, useEffect} from 'react';
  2import {useTranslation} from 'react-i18next';
  3import Layout from '../../layouts/Default';
  4import Fab from '../../containers/Fab';
  5import CarColumns from '../../containers/CarColumns';
  6import NewCarDialog from '../../containers/NewCarDialog';
  7import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
  8import EventBar from '../../containers/EventBar';
  9import useToastStore from '../../stores/useToastStore';
 10import {initializeApollo} from '../../lib/apolloClient';
 11import ErrorPage from '../_error';
 12import {
 13  useUpdateEventMutation,
 14  Event as EventType,
 15  useEventByUuidQuery,
 16  EventByUuidDocument,
 17} from '../../generated/graphql';
 18import useEventStore from '../../stores/useEventStore';
 19import Loading from '../../containers/Loading';
 20
 21const POLL_INTERVAL = 10000;
 22
 23interface Props {
 24  event: EventType;
 25  eventUUID: string;
 26}
 27
 28const EventPage = props => {
 29  const {event} = props;
 30  const {t} = useTranslation();
 31
 32  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 33
 34  return <Event {...props} />;
 35};
 36
 37const Event = (props: Props) => {
 38  const {eventUUID} = props;
 39  const {t} = useTranslation();
 40  const addToast = useToastStore(s => s.addToast);
 41  const setEvent = useEventStore(s => s.setEvent);
 42  const eventUpdate = useEventStore(s => s.event);
 43  const setIsEditing = useEventStore(s => s.setIsEditing);
 44  const [updateEvent] = useUpdateEventMutation();
 45  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 46  const [openNewCar, toggleNewCar] = useReducer(i => !i, false);
 47  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 48    pollInterval: POLL_INTERVAL,
 49    variables: {uuid: eventUUID},
 50  });
 51
 52  useEffect(() => {
 53    if (event) setEvent(event as EventType);
 54  }, [event]);
 55
 56  const onSave = async e => {
 57    try {
 58      const {uuid, ...data} = eventUpdate;
 59      delete data.id;
 60      delete data.__typename;
 61      delete data.cars;
 62      delete data.waitingList;
 63      await updateEvent({variables: {uuid, eventUpdate: data}});
 64      setIsEditing(false);
 65    } catch (error) {
 66      console.error(error);
 67      addToast(t('event.errors.cant_update'));
 68    }
 69  };
 70
 71  const onShare = async () => {
 72    if (!event) return null;
 73    // If navigator as share capability
 74    if (!!navigator.share)
 75      return await navigator.share({
 76        title: `Caroster ${event.name}`,
 77        url: `${window.location.href}`,
 78      });
 79    // Else copy URL in clipboard
 80    else if (!!navigator.clipboard) {
 81      await navigator.clipboard.writeText(window.location.href);
 82      addToast(t('event.actions.copied'));
 83      return true;
 84    }
 85  };
 86
 87  if (!event) return <Loading />;
 88
 89  return (
 90    <Layout
 91      pageTitle={t('event.title', {title: event.name})}
 92      menuTitle={t('event.title', {title: event.name})}
 93      displayMenu={false}
 94    >
 95      <EventBar
 96        event={event}
 97        onAdd={setIsAddToMyEvent}
 98        onSave={onSave}
 99        onShare={onShare}
100      />
101      <CarColumns toggleNewCar={toggleNewCar} />
102      <Fab onClick={toggleNewCar} open={openNewCar} aria-label="add-car" />
103      <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
104      <AddToMyEventDialog
105        event={event}
106        open={isAddToMyEvent}
107        onClose={() => setIsAddToMyEvent(false)}
108      />
109    </Layout>
110  );
111};
112
113export async function getServerSideProps(ctx) {
114  const {uuid} = ctx.query;
115  const apolloClient = initializeApollo();
116  const {data = {}} = await apolloClient.query({
117    query: EventByUuidDocument,
118    variables: {uuid},
119  });
120  const {eventByUUID: event} = data;
121  const {host = ''} = ctx.req.headers;
122
123  return {
124    props: {
125      event,
126      eventUUID: uuid,
127      metas: {
128        title: event?.name || '',
129        url: `https://${host}${ctx.resolvedUrl}`,
130      },
131    },
132  };
133}
134
135export default EventPage;